<?php

class Workset_Iconv {

   private static $instance = null;

        //это собственно те кодировки который поддерживает данный класс,
        //можно дописать другие
   private static $encodings = array(
      "utf8" => "UTF-8",
      "cp1251" => "WINDOWS-1251",
   );

   private $internalEncoding = "";

   private $inputEncoding = "";

   private $outputEncoding = "";

   private function __construct() {}

   /**
   *   Singleton instance
   *   @return Charset_Converter
   */
   public static function getInstance() {
      if (self::$instance === null) {
         self::$instance = new self();
      }
      return self::$instance;
   }

   /**
   *   set internal encoding
   *   @param string $encoding
   */
   public function setInternalEncoding($encoding) {
      iconv_set_encoding("internal_encoding", $this->internalEncoding = (isset(self::$encodings[$encoding]) ? self::$encodings[$encoding] : $encoding));
   }

   /**
   *   set input encoding
   *   @param string $encoding
   */
   public function setInputEncoding($encoding) {
      iconv_set_encoding("input_encoding", $this->inputEncoding = (isset(self::$encodings[$encoding]) ? self::$encodings[$encoding] : $encoding));
   }

   /**
   *   set output encoding
   *   @param string $encoding
   */
   public function setOutputEncoding($encoding) {
      iconv_set_encoding("output_encoding", $this->outputEncoding = (isset(self::$encodings[$encoding]) ? self::$encodings[$encoding] : $encoding));
   }

   /**
   *   get internal encoding
   */
   public function getInternalEncoding() {
      return $this->internalEncoding;
   }

   /**
   *   get input encoding
   */
   public function getInputEncoding() {
      return $this->inputEncoding;
   }

   /**
   *   get output encoding
   */
   public function getOutputEncoding() {
      return $this->outputEncoding;
   }

   /**
   *   set all encodings (inernal, input and output)
   */
   public function setEncoding($arEncoding) {
      foreach ($arEncoding as $key => $value) {
         switch ($key) {
            case "internal_encoding":
               $this->setInternalEncoding($value);
            break;

            case "input_encoding":
               $this->setInputEncoding($value);
            break;

            case "output_encoding":
               $this->setOutputEncoding($value);
            break;
         }
      }
   }

   /**
   * @param string $name
   * @param array $args
   *
   * For example:
   *   $iconv->cp1251_utf8($str); //convert string in cp1251 to utf8
   *   $iconv->_utf8($str); //convert string in default input encoding (set by setEncoding method) to utf8
   *   $iconv->_($str); //convert string in default input encoding to default output encoding
   *   $iconv->cp1251($str); //convert in cp1251 to default output encoding
   *
   */
   public function __call($name, $args) {
      $arConverts = explode("_", $name);
      $inputEnc = !empty($arConverts[0]) && (isset(self::$encodings[current($arConverts)]))
                  ? self::$encodings[current($arConverts)]
                  : $this->getInputEncoding();

      $outputEnc = isset($arConverts[1]) && isset(self::$encodings[$arConverts[1]])
                  ? self::$encodings[$arConverts[1]]
                  : $this->getOutputEncoding();

      if ($inputEnc && $outputEnc)
      {
         $result = current($args);
         if (is_array($result)) {
            return $this->_convertArray($result, $inputEnc, $outputEnc);
         } else if (is_string($result)) {
            return iconv($inputEnc, $outputEnc, $result);
         } else {
            return $result;
         }
      }
      return false;
   }

   /**
   * Use this for set obStart output handler
   *
   * @param string $content
   * @param int $status
   */
   public function outputHandler($content, $status = 1) {
      if ($this->internalEncoding && $this->outputEncoding) {
         return ob_iconv_handler($content, $status);
      }
   }

   private function _convertArray(&$ar, $inputEnc, $outputEnc) {
      foreach ($ar as &$value) {
         if (is_array($value)) {
            $this->_convertArray($value, $inputEnc, $outputEnc);
         } else {
            $value = iconv($inputEnc, $outputEnc, $value);
         }
      }
      return $ar;
   }
}

?>